#!/usr/bin/env python
# Copyright 2013 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Code generator for Ozone platform list.

This script takes as arguments a list of platform names and generates a C++
source file containing a list of those platforms.

Each platform gets an integer identifier that is used to find objects for that
platform (particularly constructors for platform-specific objects).

Example Output: ./generate_ozone_platform_list.py --default wayland dri wayland

  // platform_list.txt

  wayland
  dri

  // platform_list.h

  #ifndef UI_OZONE_PLATFORM_LIST_H_
  #define UI_OZONE_PLATFORM_LIST_H_

  namespace ui {

  const int kPlatformWayland = 0;
  const int kPlatformDri = 1;

  extern const char *kPlatformNames[kPlatformCount];

  }  // namespace ui

  // platform_list.cc

  #include "ui/ozone/platform_list.h"

  namespace ui {

  const char *kPlatformNames[] = {
   "wayland", // kPlatformWayland
   "dri", // kPlatformDri
  };

  }  // namespace ui

  #endif  // UI_OZONE_PLATFORM_LIST_H_

"""

try:
    from StringIO import StringIO  # for Python 2
except ImportError:
    from io import StringIO  # for Python 3
import optparse
import os
import collections
import re
import sys


def GetConstantName(name):
  """Determine name of static constructor function from platform name.

  We just capitalize the platform name and prepend "CreateOzonePlatform".
  """

  return 'kPlatform' + name.capitalize()


def GeneratePlatformListText(out, platforms):
  """Generate text file with list of platform names, in platform id order."""

  for platform in platforms:
    out.write(platform)
    out.write('\n')

  out.write('\n')


def GeneratePlatformListHeader(out, platforms):
  """Generate ids of ozone platforms & declaration of static names array."""

  out.write('// DO NOT MODIFY. GENERATED BY generate_ozone_platform_list.py\n')
  out.write('\n')

  out.write('#ifndef UI_OZONE_PLATFORM_LIST_H_\n')
  out.write('#define UI_OZONE_PLATFORM_LIST_H_\n')
  out.write('\n')

  out.write('namespace ui {\n')
  out.write('\n')

  # Prototypes for platform initializers.
  for plat_id, plat_name in enumerate(platforms):
    out.write('const int %s = %d;\n' % (GetConstantName(plat_name), plat_id))
  out.write('\n')

  # Platform count.
  out.write('const int kPlatformCount = %d;\n' % len(platforms))
  out.write('\n')

  # Declaration for names list.
  out.write('extern const char* kPlatformNames[kPlatformCount];\n')
  out.write('\n')

  out.write('}  // namespace ui\n')
  out.write('\n')

  out.write('#endif  // UI_OZONE_PLATFORM_LIST_H_\n')
  out.write('\n')


def GeneratePlatformListSource(out, platforms):
  """Generate static array containing a list of ozone platforms."""

  out.write('// DO NOT MODIFY. GENERATED BY generate_ozone_platform_list.py\n')
  out.write('\n')

  out.write('#include "ui/ozone/platform_list.h"\n')
  out.write('\n')

  out.write('namespace ui {\n')
  out.write('\n')

  # Definition of names list.
  out.write('const char* kPlatformNames[] = {\n')

  # Prototypes for platform initializers.
  for plat_name in platforms:
    out.write('    "%s",  // %s\n' % (plat_name, GetConstantName(plat_name)))
  out.write('};\n')
  out.write('\n')

  out.write('}  // namespace ui\n')
  out.write('\n')


def main(argv):
  parser = optparse.OptionParser()
  parser.add_option('--output_cc')
  parser.add_option('--output_h')
  parser.add_option('--output_txt')
  parser.add_option('--default')
  options, platforms = parser.parse_args(argv)

  # Reorder the platforms when --default is specified.
  # The default platform must appear first in the platform list.
  if options.default and options.default in platforms:
    platforms.remove(options.default)
    platforms.insert(0, options.default)

  # Write to standard output or file specified by --output_{cc,h}.
  out_cc = getattr(sys.stdout, 'buffer', sys.stdout)
  out_h = getattr(sys.stdout, 'buffer', sys.stdout)
  out_txt = getattr(sys.stdout, 'buffer', sys.stdout)
  if options.output_cc:
    out_cc = open(options.output_cc, 'wb')
  if options.output_h:
    out_h = open(options.output_h, 'wb')
  if options.output_txt:
    out_txt = open(options.output_txt, 'wb')

  out_txt_str = StringIO()
  out_h_str = StringIO()
  out_cc_str = StringIO()

  GeneratePlatformListText(out_txt_str, platforms)
  out_txt.write(out_txt_str.getvalue().encode('utf-8'))
  GeneratePlatformListHeader(out_h_str, platforms)
  out_h.write(out_h_str.getvalue().encode('utf-8'))
  GeneratePlatformListSource(out_cc_str, platforms)
  out_cc.write(out_cc_str.getvalue().encode('utf-8'))

  if options.output_cc:
    out_cc.close()
  if options.output_h:
    out_h.close()
  if options.output_txt:
    out_txt.close()

  return 0


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
